/**
Copyright (c) 2008 Panayiotis Mavrommatis

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

/**
 * GGPerson: Encapsulates public and app-specific information about
 * a person.
 */ 
function GGPerson(id) {
  this._id = id;
}

GGPerson.prototype._id;
GGPerson.prototype._name;
GGPerson.prototype._image;
GGPerson.prototype._imagesize;
GGPerson.prototype._profile;
GGPerson.prototype._gglocation;
GGPerson.prototype._undo_gglocation;  // Previous location to which we can undo

GGPerson.prototype.getId = function() {
  return this._id;
};
GGPerson.prototype.getName = function() {
  return this._name;
};
GGPerson.prototype.getImage = function() {
  return this._image;
};
GGPerson.prototype.getImageSize = function() {
  if (typeof(this._imagesize) != 'undefined') {
    var x = this._imagesize.x;
    var y = this._imagesize.y;
    var ratio = 36 / Math.max(x, y);
    return new GSize(Math.round(x * ratio), Math.round(y * ratio));
  } else {
    return new GSize(36, 36);
  }
};
GGPerson.prototype.getProfile = function() {
  return this._profile;
};
GGPerson.prototype.getGGLocation = function() {
  return this._gglocation;
};
GGPerson.prototype.getUndoGGLocation = function() {
  return this._undo_gglocation;
};
GGPerson.prototype.setName = function(name) {
  this._name = name;
};
GGPerson.prototype.setImage = function(image) {
  // This orkut gif does not actually work when the request is made
  // from google maps.
  if (!image || image.match("orkut.com/img/i_nophoto")) {
    this._image = "http://geograffr.googlecode.com/svn/trunk/nophoto.png";
  } else {
    this._image = image;
  }
};
GGPerson.prototype.setImageSize = function(imagesize) {
  this._imagesize = imagesize;
}
GGPerson.prototype.setProfile = function(profile) {
  this._profile = profile;
};
GGPerson.prototype.setGGLocation = function(gglocation) {
  this._gglocation = gglocation;
};
GGPerson.prototype.setUndoGGLocation = function(gglocation) {
  this._undo_gglocation = gglocation;
};

// A SocialGraphControl is a simple text button that shows/hides
// the social graph from the map.
function SocialGraphControl() {
};
SocialGraphControl.prototype = new GControl();
SocialGraphControl.prototype.initialize = function(map) {
  var container = document.createElement("div");

  var buttonDiv = document.createElement("div");
  this.setButtonStyle_(buttonDiv, false);
  container.appendChild(buttonDiv);
  buttonDiv.appendChild(document.createTextNode("Social Graph"));
  GEvent.addDomListener(buttonDiv, "click", function() {
      ggSocialToggled = !ggSocialToggled;
      SocialGraphControl.prototype.setButtonStyle_(buttonDiv, ggSocialToggled);
			toggleSocialGraphLines(ggSocialToggled);
  });

  map.getContainer().appendChild(container);
  return container;
};
SocialGraphControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(5, 5));
};
SocialGraphControl.prototype.setButtonStyle_ = function(button, toggled) {
  button.style.textDecoration = "none";
  button.style.color = "#444";
  button.style.font = "small Arial";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "10em";
  button.style.cursor = "pointer";
  if (toggled) {
    button.style.backgroundColor = "#eee";
    button.style.borderTop = "2px solid #666";
    button.style.borderLeft = "2px solid #666";
    button.style.borderBottom = "2px solid #bbb";
    button.style.borderRight = "2px solid #bbb";
  } else {
    button.style.backgroundColor = "white";
    button.style.borderTop = "2px solid #bbb";
    button.style.borderLeft = "2px solid #bbb";
    button.style.borderBottom = "2px solid #666";
    button.style.borderRight = "2px solid #666";
  }
};

function toggleSocialGraphLines(ggSocialToggled){
	for(var line in ggSocialGraphLines){
		if (ggSocialToggled)
		{
			ggSocialGraphLines[line].show();
		}else {
			ggSocialGraphLines[line].hide();
		}
	}
}

function addSocialGraphLine(map, ggLocation1, ggLocation2){
	if (!ggSocialGraphLocationsMap[[ggLocation2, ggLocation1]]){
		var polyline = new GPolyline([ggLocation1, ggLocation2], "#3366cc", 3, 0.5);
		polyline.hide();
		map.addOverlay(polyline);
		ggSocialGraphLines.push(polyline);
		ggSocialGraphLocationsMap[[ggLocation1, ggLocation2]] = true;
	}
}

// Global objects
var ggOwnerPerson;
var ggFofs;  // friends of the owner's friends.
var ggSocialToggled = false;
var ggSocialGraphLines = [];
var ggSocialGraphLocationsMap = [];
var ggFriendLocations = [];
var ggRightClickLocation;
var ggMouseMoveListenerHandle;
var ggLeftClickListenerHandle;
var ggBoundPolygon;

// Debug methods
function ggDebug(message) {
  if (typeof(console) != 'undefined') {
    console.log(message);
  }
};

// Unescapes the data from json.
function unhtmlify(input) {
  return input.replace(/&#(\d+);/g,  function() {
      return String.fromCharCode(arguments[1]);
    });
};

// On load, getData() is called.
gadgets.util.registerOnLoadHandler(getData);

/**
 * Requests owner, viewer, owner_friends and app data for owner and
 * owner_friends.
 */
function getData() {
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest('OWNER'), 'owner');
  req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
  req.add(req.newFetchPersonAppDataRequest('OWNER', 'gglocation'),
          'appdata');
  req.add(req.newFetchPersonAppDataRequest('OWNER_FRIENDS', 'gglocation'),
          'frienddata');
  req.add(req.newFetchPersonAppDataRequest('OWNER_FRIENDS', 'ggfof'),
          'fofdata');
  req.add(req.newFetchPersonAppDataRequest('OWNER', 'ggimagesize'),
          'ggownerimagesizedata');
  req.add(req.newFetchPersonAppDataRequest('OWNER_FRIENDS', 'ggimagesize'),
          'ggimagesizedata');

  // We fetch the owner's friends (only those who have the app installed)
  var opt_params = {};
  opt_params[opensocial.DataRequest.PeopleRequestFields.FILTER] =
    opensocial.DataRequest.FilterType.HAS_APP;
  req.add(req.newFetchPeopleRequest('OWNER_FRIENDS', opt_params),
          'ownerFriends');
  req.send(onLoadFriends);
};

/**
 * Gets the responses from our requests and creates data structures
 * for use in subsequent methods.
 *
 * @param {opensocial.DataResponse} dataResponse the response.
 */
function onLoadFriends(dataResponse) {
  // Viewer
  var viewerId = 'unknown_viewer';
  var viewer = dataResponse.get('viewer').getData();
  if (viewer) {
    viewerId = viewer.getId();
  }
  var viewerPerson = new GGPerson(viewerId);

  // Owner
  var ownerId = 'unknown_owner';
  var owner = dataResponse.get('owner').getData();
  if (owner) {
    ownerId = owner.getId();
  }
  ggOwnerPerson = new GGPerson(ownerId);
  ggOwnerPerson.setName(owner.getDisplayName());
  ggOwnerPerson.setImage(owner.getField(opensocial.Person.Field.THUMBNAIL_URL));
  ggOwnerPerson.setProfile(owner.getField(opensocial.Person.Field.PROFILE_URL));
  
  var gpoint = new GLatLng(0, 0);
  var appdata = dataResponse.get('appdata').getData();
  if (appdata &&
      (owner.getId() in appdata) &&
      ('gglocation' in appdata[owner.getId()])) {
    var gglocation = appdata[owner.getId()]['gglocation'];
    try {
      var gglocation_parsed = gadgets.json.parse(unhtmlify(gglocation));
      gpoint = new GLatLng(gglocation_parsed.y, gglocation_parsed.x);
    } catch (e) {
      ggDebug(e);
    }
  } else {  // no app data for this user, try to parse their address
    var ownerAddresses = owner.getField(opensocial.Person.Field.ADDRESSES);
    if (ownerAddresses.length > 0) {
      var ownerAddress = ownerAddresses[0];
      var longitude = ownerAddress.getField(opensocial.Address.Field.LONGITUDE);
      var latitude =  ownerAddress.getField(opensocial.Address.Field.LATITUDE);

      if (longitude && latitude) { // hack alert: 0,0 is screwed
        gpoint = new GLatLng(latitude, longitude);
      } else {
        var searchAddress =
          ownerAddress.getField(opensocial.Address.Field.LOCALITY)
          + ' ' + ownerAddress.getField(opensocial.Address.Field.REGION)
          + ' ' + ownerAddress.getField(opensocial.Address.Field.COUNTRY);
        // TODO: geoencode the address
      }
    }
  }
  ggOwnerPerson.setGGLocation(gpoint);

  // Owner's friends
  var friendMap = {};
  var friendList = [];
  var ownerFriends = dataResponse.get('ownerFriends').getData();
  var frienddata = dataResponse.get('frienddata').getData();

  ownerFriends.each(function(person) {
      friendPerson = new GGPerson(person.getId());
      friendPerson.setName(person.getDisplayName());
      friendPerson.setImage(person.getField(opensocial.Person.Field.
                                            THUMBNAIL_URL));
      friendPerson.setProfile(person.getField(opensocial.Person.Field.
                                              PROFILE_URL));
      var gpoint = new GLatLng(0, 0);
      try {
        var json = frienddata[person.getId()]['gglocation'];
        var json_parsed = gadgets.json.parse(unhtmlify(json));
        gpoint = new GLatLng(json_parsed.y, json_parsed.x);
      } catch (e) {
        ggDebug(e);
      }
      friendPerson.setGGLocation(gpoint);
      friendMap[person.getId()] = friendPerson;
      friendList.push(person.getId());
    });

  // fofs -- friends of friends
  ggFofs = {};
  var fofdata = dataResponse.get('fofdata').getData();
  for (var friendId in fofdata) {
    var json = fofdata[friendId]['ggfof'];
    try {
      var json_parsed = gadgets.json.parse(unhtmlify(json));
      ggFofs[friendId] = json_parsed;
    } catch (e) {
      ggDebug(e);
    }
  }
  ggDebug("ggFofs");
  ggDebug(ggFofs);

  // Image sizes
  var ggOwnImageSizeData = dataResponse.get('ggownerimagesizedata').getData();
  try {
    var json = ggOwnImageSizeData[ggOwnerPerson.getId()]['ggimagesize'];
    ggOwnerPerson.setImageSize(gadgets.json.parse(unhtmlify(json)));
  } catch (e) {
    ggDebug(e);
  }

  var ggImageSizeData = dataResponse.get('ggimagesizedata').getData();
  for (var friendId in ggImageSizeData) {
    try {
      var json = ggImageSizeData[friendId]['ggimagesize'];
      friendMap[friendId].setImageSize(gadgets.json.parse(unhtmlify(json)));
    } catch (e) {
      ggDebug(e);
    }
  }

  // Update our fofs when owner == viewer
  if (viewerPerson.getId() == ggOwnerPerson.getId()) {
    // TODO: Do this only if the friendList has changed.
    ggDebug("friendList");
    ggDebug(friendList);
    PersistOwnerFriends(friendList);
    PersistOwnerImageSize();
  }
  
  loadMap(viewerPerson, friendMap, ggFofs);
};

function PersistOwnerImageSize() {
  ggDebug("Owner Image:");
  ggDebug(ggOwnerPerson.getImage());
  var ownerImage = document.createElement('img');
  ownerImage.setAttribute('id', 'ggOwnerImage');
  ownerImage.setAttribute('src', ggOwnerPerson.getImage());
  ownerImage.setAttribute('style', 'display:none;');
  ownerImage.setAttribute('onLoad', 'OwnerImageLoaded()');
  document.getElementById('parent').appendChild(ownerImage);
}

/**
 * Called when the owner image has finished loading.
 */
function OwnerImageLoaded() {
  ggDebug("Owner Image finished loading");
  image = document.getElementById('ggOwnerImage');
  // Guard against something gone wrong
  if (!image || !image.width || image.width < 10 || !image.height ||
      image.height < 10) {
    ggDebug("Image not found/ too small.");
    return;
  }
  var json = gadgets.json.stringify(new GPoint(image.width, image.height));
  var request = opensocial.newDataRequest();
  request.add(request.newUpdatePersonAppDataRequest('VIEWER', 'ggimagesize',
                                                    json));
  request.send();
}

function PersistOwnerFriends(friendList) {
  var json = gadgets.json.stringify(friendList);
  ggDebug("PersistOwnerFriends json");
  ggDebug(json);
  var request = opensocial.newDataRequest();
  var update = request.newUpdatePersonAppDataRequest('VIEWER', 'ggfof', json);
  request.add(update, "updata");
  request.send();
}

function setMyLocation(location) {
  var json = gadgets.json.stringify(location);
  var request = opensocial.newDataRequest();
  var update = request.newUpdatePersonAppDataRequest('VIEWER', 'gglocation',
                                                     json);   
  request.add(update, "updata");
  ggOwnerPerson.setUndoGGLocation(ggOwnerPerson.getGGLocation());
  ggOwnerPerson.setGGLocation(location);
  request.send(UpdateDone, "updata");
}

function UpdateDone(updata) {
  // TODO: Actually check updata :)

  var parent = document.getElementById('parent');
  var notification = document.createElement('div');
  notification.setAttribute('id', 'ggNotification');
  var message = "You location was successfully modified";
  notification.appendChild(document.createTextNode(message));
  notification.setAttribute('class', 'ggNotification');

  var undo = document.createElement('span');
  undo.appendChild(document.createTextNode('undo'));
  undo.setAttribute('class', 'ggNotificationButton');
  undo.setAttribute('onclick', 'UndoSetLocation()');
  //  notification.appendChild(undo);

  var close = document.createElement('span');
  close.appendChild(document.createTextNode('hide'));
  close.setAttribute('class', 'ggNotificationButton');
  close.setAttribute('onclick', 'HideNotification(\'ggNotification\')');
  notification.appendChild(close);

  parent.appendChild(notification);
  setTimeout('HideNotification(\'ggNotification\')', 20000);
}

function UndoSetLocation() {
  // TODO: Actually undo.
}

function HideNotification(elementId) {
  var parent = document.getElementById('parent');
  var element = document.getElementById(elementId);
  try {
    parent.removeChild(element);
  } catch (e) {
    // if the child was already removed, we are fine.
  }
}


/**
* Displays our information on a map
*/
function loadMap(viewerPerson, friendsMap, ggFofs) {
  var parent = document.getElementById('parent');
  var mapDiv = document.createElement('div');
  mapDiv.setAttribute('id', 'geograff_map');
  mapDiv.setAttribute('style', 'width: 500px; height:280px;');
  parent.appendChild(mapDiv);

  if (GBrowserIsCompatible()) {
    var map = new GMap2(mapDiv);
    map.addControl(new GSmallZoomControl());
    map.addControl(new SocialGraphControl());
    map.setCenter(ggOwnerPerson.getGGLocation());
		GEvent.addListener(map, "singlerightclick", function(pixel,url,obj){
			var latlng = map.fromContainerPixelToLatLng(pixel); 
			handleRightClick(map, latlng);
		});
     

    var bounds = new GLatLngBounds();

    // Add the owner's marker
    createOwnerMarker(viewerPerson, map, bounds);
    
    for (var personId in friendsMap){
      if (personId == ggOwnerPerson.getId()) {
        continue;
      }
      var ggperson = friendsMap[personId];
      var friendIcon = new GIcon();
      friendIcon.image = ggperson.getImage();
      var imageSize = ggperson.getImageSize();
      friendIcon.iconSize = imageSize;
      friendIcon.iconAnchor = new GPoint(Math.round(imageSize.width / 2),
                                         imageSize.height + 10);
      friendIcon.infoWindowAnchor = new GPoint(Math.round(imageSize.width / 2),
                                               6);

      var borderIcon = new GIcon();
      borderIcon.image = "http://geograffr.googlecode.com/svn/trunk/pin.png";
      borderIcon.iconSize = new GSize(36, 10);
      borderIcon.iconAnchor = new GPoint(18, 10);
      var borderMarker = new GMarker(ggperson.getGGLocation(), borderIcon);
      map.addOverlay(borderMarker);
      
      var friendMarker = new GMarker(ggperson.getGGLocation(), friendIcon);
      map.addOverlay(friendMarker);
      bounds.extend(ggperson.getGGLocation());
      ggFriendLocations.push(ggperson.getGGLocation());
  
      iwContents = createInfoWindowContents(ggperson.getImage(),
                                            ggperson.getName(),
                                            ggperson.getProfile());
      var opts = {};
      opts['maxWidth'] = '150';
      friendMarker.bindInfoWindow(iwContents, opts); 

      addSocialGraphLine(map, ggOwnerPerson.getGGLocation(), ggperson.getGGLocation());			
      
      var ggPersonFriends = ggFofs[personId];
      
      for (var fofId in ggPersonFriends){
        var fofPerson = friendsMap[ggPersonFriends[fofId]];
        if (fofPerson){
          addSocialGraphLine(map, ggperson.getGGLocation(), fofPerson.getGGLocation());
        }
      }
    }

    // Extend our bounds and auto-zoom the map so all our friends are visible.
    adjustMapBounds(map, bounds);
  }

  _IG_AdjustIFrameHeight();
}

function createOwnerMarker(viewerPerson, map, bounds) {
  // If owner == viewer, we add a red draggable marker
  if (ggOwnerPerson.getId() == viewerPerson.getId()) {
    var ownerMarker = new GMarker(ggOwnerPerson.getGGLocation(),
                                  {draggable: true});
    map.addOverlay(ownerMarker);
    bounds.extend(ggOwnerPerson.getGGLocation());
		ggFriendLocations.push(ggOwnerPerson.getGGLocation());

    var iwContents = createOwnerInfoWindowContents(viewerPerson);
    var opts = {};
    opts['maxWidth'] = '150';
    ownerMarker.bindInfoWindow(iwContents, opts);

    // Add a drop listener
    GEvent.addListener(ownerMarker, "dragend", 
                       function(){
                         setMyLocation(ownerMarker.getLatLng());
                       });
  } else {
    // If owner != viewer, add a picture with a border
    var borderIcon = new GIcon();
    borderIcon.image = "http://geograffr.googlecode.com/svn/trunk/borderpin.png";
    borderIcon.shadow = "http://geograffr.googlecode.com/svn/trunk/borderpinshadow.png"; 
    borderIcon.iconSize = new GSize(44, 54);
    borderIcon.iconAnchor = new GPoint(22, 54);
    borderIcon.shadowSize = new GSize(77, 54);
    var borderMarker = new GMarker(ggOwnerPerson.getGGLocation(), borderIcon);
    map.addOverlay(borderMarker);

    // Picture
    var ownerIcon = new GIcon();
    ownerIcon.image = ggOwnerPerson.getImage();
    var imageSize = ggOwnerPerson.getImageSize();
    ownerIcon.iconSize = imageSize;
    ownerIcon.iconAnchor = new GPoint(Math.round(imageSize.width / 2), 50);
    ownerIcon.infoWindowAnchor = new GPoint(Math.round(imageSize.width / 2),
                                            6);
    var ownerMarker = new GMarker(ggOwnerPerson.getGGLocation(), ownerIcon);
    map.addOverlay(ownerMarker);
    bounds.extend(ggOwnerPerson.getGGLocation());
    iwContents = createInfoWindowContents(ggOwnerPerson.getImage(),
                                          ggOwnerPerson.getName(),
                                          ggOwnerPerson.getProfile());
    ownerMarker.bindInfoWindow(iwContents, {maxWidth: 150}); 
  }
}

function createInfoWindowContents(image_url, displayName, profile_url){
  var iwContents = document.createElement('div');
  var iwImage = document.createElement('img');
  iwImage.setAttribute('src', image_url);
  iwImage.setAttribute('style', 'float: left;');
  
  var iwName = document.createElement('div');
  iwName.setAttribute('style', 'font-weight: bold;');
  iwName.appendChild(document.createTextNode(displayName));
  
  var iwAnchor = document.createElement('a');
  iwAnchor.setAttribute('href', profile_url);
  iwAnchor.setAttribute('target', '_parent');
  iwAnchor.setAttribute('style', 'font-size: 10pt;');
  iwAnchor.appendChild(document.createTextNode("Profile"));

  iwContents.appendChild(iwImage);
  iwContents.appendChild(iwName);  
  iwContents.appendChild(iwAnchor);

  return iwContents;
}

function createOwnerInfoWindowContents(viewerPerson) {
  var iwContents = document.createElement('div');

  var title = "You are here";
  if (viewerPerson.getId() != ggOwnerPerson.getId()) {
    title = ggOwnerPerson.getName() + " is here";
  }

  var iwName = document.createElement('div');
  iwName.setAttribute('style', 'font-weight: bold;');
  iwName.appendChild(document.createTextNode(title));
  iwContents.appendChild(iwName);

  if (viewerPerson.getId() == ggOwnerPerson.getId()) {
    var dragMessage = document.createElement('div');
    dragMessage.setAttribute('style', 'padding-top: 0.5em; color: #666; font-size: 9pt;');
    dragMessage.appendChild(document.createTextNode("Drag & Drop the red marker to change your location."));
    iwContents.appendChild(dragMessage);  
  }

  return iwContents;
}


// Handles a right click event. 
function handleRightClick(map, latlng){
	// Check if this is the first right click
	if (!ggRightClickLocation){
		ggRightClickLocation = latlng;
		ggMouseMoveListenerHandle = GEvent.addListener(map, "mousemove", function(point){
			handleMouseMove(map, point);
		});

		/*
		ggLeftClickListenerHandle = GEvent.addListener(map, "click", function(overlay, pixel){
			var clickLatLng = map.fromContainerPixelToLatLng(pixel); 
			handleRightClick(map, clickLatLng);
		});*/
	} else {
		var clickBounds = new GLatLngBounds();
		clickBounds.extend(ggRightClickLocation);
		clickBounds.extend(latlng);

		var newBounds = new GLatLngBounds();
		var selectedFriends = 0;
		for(var i in ggFriendLocations){
			if (clickBounds.containsLatLng(ggFriendLocations[i])){
				newBounds.extend(ggFriendLocations[i]);
				selectedFriends++;
			}
		}
		
		if (selectedFriends > 0){
			adjustMapBounds(map, newBounds);
		}
		
		GEvent.removeListener(ggMouseMoveListenerHandle);
		//GEvent.removeListener(ggLeftClickListenerHandle);
		map.removeOverlay(ggBoundPolygon);
		ggRightClickLocation = 0;
	}	
}


// Handles mouse move events after right click has been pressed.
// Redraws the polygon to highlight the selected area.
function handleMouseMove(map, latlng){
		if (ggBoundPolygon){
			map.removeOverlay(ggBoundPolygon);
		}
		
		ggBoundPolygon = drawBoundPolygon(ggRightClickLocation, latlng);
		map.addOverlay(ggBoundPolygon);
}


// Returns a new GPolygon, with latlng1 and latlng2 as its two oposite corners
function drawBoundPolygon(latlng1, latlng2){
	var polygon = new GPolygon([
		new GLatLng(Math.max(latlng1.lat(), latlng2.lat()), Math.max(latlng1.lng(), latlng2.lng())),
		new GLatLng(Math.min(latlng1.lat(), latlng2.lat()), Math.max(latlng1.lng(), latlng2.lng())),
		new GLatLng(Math.min(latlng1.lat(), latlng2.lat()), Math.min(latlng1.lng(), latlng2.lng())),
		new GLatLng(Math.max(latlng1.lat(), latlng2.lat()), Math.min(latlng1.lng(), latlng2.lng())),
		new GLatLng(Math.max(latlng1.lat(), latlng2.lat()), Math.max(latlng1.lng(), latlng2.lng()))
		], "#f33f00", 5, 1, "#ff0000", 0.2);

	return polygon;
}


// Extend our bounds and adjusts zoom level 
function adjustMapBounds(map, bounds){
  var northEastBound = bounds.getNorthEast();
  var southWestBound = bounds.getSouthWest();
  var latExt = (northEastBound.lat() - southWestBound.lat()) * 0.05;
  var lngExt = (northEastBound.lng() - southWestBound.lng()) * 0.05;
  bounds.extend(new GLatLng(northEastBound.lat() + 4*latExt,
                              northEastBound.lng() + lngExt));
  bounds.extend(new GLatLng(southWestBound.lat(),
                              southWestBound.lng() - lngExt));
  map.setZoom(map.getBoundsZoomLevel(bounds));
  map.setCenter(bounds.getCenter());
}


//